import { Injectable } from '@angular/core'
import { I18NService } from '@core'
import { IOption, IFormItem, FormItemType, CardChanCodeValue } from '@shared/interfaces/common'
import {
  VisaBINMaxLength,
  IPMaxLength,
  PortMaxLength,
  ChannelMerchantNameMaxLength,
  onlyNumberReg,
  IPPattern,
  TransactionFeeReg,
  MccBINMaxLength,
  MccIcaMaxLength,
  AMEAINMaxLength,
  F3SENumPattern,
  UPIAINMaxLength,
  UPIAINLength,
  UPIChannelRemarkMaxLength,
} from 'app/utils/contraints'
import { compareTwoCurrencies, numScale, getUniqueKey } from 'app/utils/helpers'
import {
  ICardChannelVisa,
  ICardChannelMasterCard,
  ICardChannelAmericanExpress,
  ICardChannelUpiExpress,
  EAccessMode,
  AccessModeMap,
  ICardChannel,
} from '@shared/interfaces/acquirer'
import { Validators, FormControl, ValidationErrors } from '@angular/forms'
import { Observer, Observable } from 'rxjs'

const genAccessOptions = (modes: EAccessMode[]): IOption[] => {
  return modes.map(m => ({ label: AccessModeMap[m], value: m }))
}

@Injectable()
export class CardChannelService {
  private _cardChannels: ICardChannel[] = []
  constructor(private i18n: I18NService) {}

  set localCardChannels(cardChannels: ICardChannel[]) {
    this._cardChannels = cardChannels
  }

  get localCardChannels(): ICardChannel[] {
    return this._cardChannels
  }

  genVISFormItems = (currencyOptions: IOption[], handleChanMerIDChange): IFormItem[] => {
    return [
      // {
      //   label: 'WeChat Merchant ID',
      //   errTips: {
      //     required: '必填项',
      //     existed: '该渠道已存在',
      //     maxLength: '最多不超过 32 位',
      //     pattern: '格式错误：只支持数字、字母',
      //   },
      //   formControlName: 'chanMerID',
      //   change: handleChanMerIDChange,
      // },
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE') }),
        },
        formControlName: 'accessMode',
        type: FormItemType.SELECT,
        multiple: 'default',
        options: genAccessOptions([EAccessMode.CIL]),
        compareFn: (o1, o2) => o1 === o2,
      },
      {
        label: 'BIN',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'BIN' }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: VisaBINMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
          existed: this.trans('VALIDATION.CODE_EXISTS', { name: 'BIN' }),
        },
        formControlName: 'bin',
        change: handleChanMerIDChange,
        inputType: 'number',
      },
      {
        label: 'Institution Code in Offline System',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Institution Code in Offline System' }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'offlineInsCode',
        inputType: 'number',
      },
      {
        label: 'Channel Institution Code in Offline System',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Channel Institution Code in Offline System' }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'offlineChannelInsCode',
      },
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_ADDRESS_IP'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', {
            name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_ADDRESS_IP'),
          }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: IPMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.IP'),
        },
        formControlName: 'lineIP',
      },
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_PORT'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_PORT') }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: PortMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'port',
      },
      {
        label: 'Transaction Currency',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Currency' }),
        },
        formControlName: 'currencies',
        type: FormItemType.CURRENCY_SELECT,
        multiple: 'multiple',
        allowClear: true,
        options: currencyOptions,
        compareFn: compareTwoCurrencies,
      },
      {
        label: 'Transaction Fee',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Fee' }),
          pattern: this.trans('VALIDATION.PATTERN.FOUR_DECIMAL_MAX_AND_NO_NEGATIVE'),
        },
        errTip: `Transaction Fee ${this.trans('VALIDATION.PATTERN.BETWEEN_ZERO_AND_TEN_PERCENT')}`,
        type: FormItemType.INPUTGROUP,
        addAfter: '%',
        formControlName: 'fee',
        inputType: 'number',
      },
      {
        label: 'Channel Merchant Name',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Channel Merchant Name' }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: ChannelMerchantNameMaxLength }),
        },
        formControlName: 'chanMerName',
      },
    ]
  }

  genMCCFormItems = (currencyOptions: IOption[], handleChanMerIDChange): IFormItem[] => {
    return [
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE') }),
        },
        formControlName: 'accessMode',
        type: FormItemType.SELECT,
        multiple: 'default',
        options: genAccessOptions([EAccessMode.CIL]),
        compareFn: (o1, o2) => o1 === o2,
      },
      {
        label: 'BIN',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'BIN' }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: MccBINMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
          existed: this.trans('VALIDATION.CODE_EXISTS', { name: 'BIN' }),
        },
        formControlName: 'bin',
        change: handleChanMerIDChange,
        inputType: 'number',
      },
      {
        label: 'ICA',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'ICA' }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: MccIcaMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'ica',
        inputType: 'number',
      },
      {
        label: 'Institution Code in Offline System',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Institution Code in Offline System' }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'offlineInsCode',
        inputType: 'number',
      },
      {
        label: 'Channel Institution Code in Offline System',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Channel Institution Code in Offline System' }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'offlineChannelInsCode',
      },
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_ADDRESS_IP'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', {
            name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_ADDRESS_IP'),
          }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: IPMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.IP'),
        },
        formControlName: 'lineIP',
      },
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_PORT'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_PORT') }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: PortMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'port',
      },
      {
        label: 'Transaction Currency',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Currency' }),
        },
        formControlName: 'currencies',
        type: FormItemType.CURRENCY_SELECT,
        multiple: 'multiple',
        allowClear: true,
        options: currencyOptions,
        compareFn: compareTwoCurrencies,
      },
      {
        label: 'Transaction Fee',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Fee' }),
          pattern: this.trans('VALIDATION.PATTERN.FOUR_DECIMAL_MAX_AND_NO_NEGATIVE'),
        },
        errTip: `Transaction Fee ${this.trans('VALIDATION.PATTERN.BETWEEN_ZERO_AND_TEN_PERCENT')}`,
        type: FormItemType.INPUTGROUP,
        addAfter: '%',
        formControlName: 'fee',
        inputType: 'number',
      },
      {
        label: 'Channel Merchant Name',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Channel Merchant Name' }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: ChannelMerchantNameMaxLength }),
        },
        formControlName: 'chanMerName',
      },
    ]
  }

  genAMEFormItems = (currencyOptions: IOption[], handleChanMerIDChange): IFormItem[] => {
    return [
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE') }),
        },
        formControlName: 'accessMode',
        type: FormItemType.SELECT,
        multiple: 'default',
        options: genAccessOptions([EAccessMode.AME, EAccessMode.HKG]),
        compareFn: (o1, o2) => o1 === o2,
      },
      {
        label: 'AIN',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'AIN' }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: AMEAINMaxLength }),
          existed: this.trans('VALIDATION.CODE_EXISTS', { name: 'AIN' }),
        },
        formControlName: 'ain',
        change: handleChanMerIDChange,
        inputType: 'number',
      },
      {
        label: 'First 3 digits of S/E Number',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'First 3 digits of S/E Number' }),
          pattern: this.trans('VALIDATION.FIXED_LENGTH_NUM', { length: 3 }),
        },
        formControlName: 'first3DigitsOfSENumber',
        inputType: 'number',
      },
      {
        label: 'Transaction Currency',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Currency' }),
        },
        formControlName: 'currencies',
        type: FormItemType.CURRENCY_SELECT,
        multiple: 'multiple',
        allowClear: true,
        options: currencyOptions,
        compareFn: compareTwoCurrencies,
      },
      {
        label: 'Transaction Fee',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Fee' }),
          pattern: this.trans('VALIDATION.PATTERN.FOUR_DECIMAL_MAX_AND_NO_NEGATIVE'),
        },
        errTip: `Transaction Fee ${this.trans('VALIDATION.PATTERN.BETWEEN_ZERO_AND_TEN_PERCENT')}`,
        type: FormItemType.INPUTGROUP,
        addAfter: '%',
        formControlName: 'fee',
        inputType: 'number',
      },
      {
        label: 'Channel Merchant Name',
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Channel Merchant Name' }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: ChannelMerchantNameMaxLength }),
        },
        formControlName: 'chanMerName',
      },
    ]
  }

  genUPIFormItems = (currencyOptions: IOption[], handleChanMerIDChange): IFormItem[] => {
    return [
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.ACCESS_MODE') }),
        },
        formControlName: 'accessMode',
        type: FormItemType.SELECT,
        multiple: 'default',
        options: genAccessOptions([EAccessMode.UPI]),
        compareFn: (o1, o2) => o1 === o2,
      },
      {
        label: this.trans('GENERAL.INFO.CHANNEL.ACQUIRING_IIN'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.CHANNEL.ACQUIRING_IIN') }),
          minLength: this.trans('VALIDATION.FIXED_LENGTH_NUM', { length: UPIAINLength }),
          maxLength: this.trans('VALIDATION.FIXED_LENGTH_NUM', { length: UPIAINLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
          existed: this.trans('VALIDATION.CODE_EXISTS', { name: this.trans('GENERAL.INFO.CHANNEL.ACQUIRING_IIN') }),
        },
        formControlName: 'ain',
        change: handleChanMerIDChange,
        type: FormItemType.INPUTNUMBER,
      },
      {
        label: this.trans('GENERAL.INFO.CHANNEL.FOWARDING_IIN'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.CHANNEL.FOWARDING_IIN') }),
          minLength: this.trans('VALIDATION.FIXED_LENGTH_NUM', { length: UPIAINLength }),
          maxLength: this.trans('VALIDATION.FIXED_LENGTH_NUM', { length: UPIAINLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
          existed: this.trans('VALIDATION.CODE_EXISTS', { name: this.trans('GENERAL.INFO.CHANNEL.FOWARDING_IIN') }),
        },
        formControlName: 'fin',
        type: FormItemType.INPUTNUMBER,
      },
      {
        label: this.trans('GENERAL.INFO.TRANSACTION_CURRENCY'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.TRANSACTION_CURRENCY') }),
        },
        formControlName: 'currencies',
        type: FormItemType.CURRENCY_SELECT,
        multiple: 'multiple',
        allowClear: true,
        options: currencyOptions,
        compareFn: compareTwoCurrencies,
      },
      {
        label: this.trans('GENERAL.INFO.TRANSACTION_FEE'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.TRANSACTION_FEE') }),
          pattern: this.trans('VALIDATION.PATTERN.FOUR_DECIMAL_MAX_AND_NO_NEGATIVE'),
        },
        errTip: `Transaction Fee ${this.trans('VALIDATION.PATTERN.BETWEEN_ZERO_AND_TEN_PERCENT')}`,
        type: FormItemType.INPUTGROUP,
        addAfter: '%',
        formControlName: 'fee',
        inputType: 'number',
      },
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_ADDRESS_IP'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', {
            name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_ADDRESS_IP'),
          }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: IPMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.IP'),
        },
        formControlName: 'lineIP',
      },
      {
        label: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_PORT'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.CHANNEL.CARD.LINE_PORT') }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: PortMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        },
        formControlName: 'port',
      },
      {
        label: this.trans('GENERAL.INFO.CHANNEL.MERCHANT_NAME'),
        errTips: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.CHANNEL.MERCHANT_NAME') }),
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: ChannelMerchantNameMaxLength }),
        },
        formControlName: 'chanMerName',
      },
      {
        label: this.trans('GENERAL.INFO.REMARK'),
        errTips: {
          maxLength: this.trans('VALIDATION.MAX_LENGTH', { length: UPIChannelRemarkMaxLength }),
        },
        formControlName: 'remark',
      },
    ]
  }

  genVISValidateRules = (channel: ICardChannelVisa): { [key: string]: any } => {
    const localUniqueValidator = this.getLocalUniqueValidatorByChanCode(CardChanCodeValue.VIS)
    return {
      id: [null, []],
      chanCode: [channel && channel.chanCode, [Validators.required]],
      accessMode: [channel && channel.accessMode, [Validators.required]],
      bin: [
        channel && channel.bin,
        [Validators.required, Validators.maxLength(VisaBINMaxLength), Validators.pattern(onlyNumberReg)],
        [localUniqueValidator],
      ],
      offlineInsCode: [channel && channel.offlineInsCode, [Validators.required, Validators.pattern(onlyNumberReg)]],
      offlineChannelInsCode: [
        channel && channel.offlineChannelInsCode,
        [Validators.required, Validators.pattern(onlyNumberReg)],
      ],
      lineIP: [
        channel && channel.lineIP,
        [Validators.required, Validators.maxLength(IPMaxLength), Validators.pattern(IPPattern)],
      ],
      port: [
        channel && channel.port,
        [Validators.required, Validators.maxLength(PortMaxLength), Validators.pattern(onlyNumberReg)],
      ],
      currencies: [channel && channel.currencies, [Validators.required]],
      fee: [
        channel && numScale(channel.fee, 2),
        [Validators.required, Validators.min(0), Validators.max(10), Validators.pattern(TransactionFeeReg)],
      ],
      chanMerName: [
        channel && channel.chanMerName,
        [Validators.required, Validators.maxLength(ChannelMerchantNameMaxLength)],
      ],
      isLoaded: [channel && channel.isLoaded],
    }
  }

  genMCCValidateRules = (channel: ICardChannelMasterCard): { [key: string]: any } => {
    const localUniqueValidator = this.getLocalUniqueValidatorByChanCode(CardChanCodeValue.MCC)
    return {
      id: [null, []],
      chanCode: [channel && channel.chanCode, [Validators.required]],
      accessMode: [channel && channel.accessMode, [Validators.required]],
      bin: [
        channel && channel.bin,
        [Validators.required, Validators.maxLength(MccBINMaxLength), Validators.pattern(onlyNumberReg)],
        [localUniqueValidator],
      ],
      ica: [
        channel && channel.ica,
        [Validators.required, Validators.maxLength(MccIcaMaxLength), Validators.pattern(onlyNumberReg)],
      ],
      offlineInsCode: [channel && channel.offlineInsCode, [Validators.required, Validators.pattern(onlyNumberReg)]],
      offlineChannelInsCode: [
        channel && channel.offlineChannelInsCode,
        [Validators.required, Validators.pattern(onlyNumberReg)],
      ],
      lineIP: [
        channel && channel.lineIP,
        [Validators.required, Validators.maxLength(IPMaxLength), Validators.pattern(IPPattern)],
      ],
      port: [
        channel && channel.port,
        [Validators.required, Validators.maxLength(PortMaxLength), Validators.pattern(onlyNumberReg)],
      ],
      currencies: [channel && channel.currencies, [Validators.required]],
      fee: [
        channel && numScale(channel.fee, 2),
        [Validators.required, Validators.min(0), Validators.max(10), Validators.pattern(TransactionFeeReg)],
      ],
      chanMerName: [
        channel && channel.chanMerName,
        [Validators.required, Validators.maxLength(ChannelMerchantNameMaxLength)],
      ],
      isLoaded: [channel && channel.isLoaded],
    }
  }

  genAMEValidateRules = (channel: ICardChannelAmericanExpress): { [key: string]: any } => {
    const localUniqueValidator = this.getLocalUniqueValidatorByChanCode(CardChanCodeValue.AME)
    return {
      id: [null, []],
      chanCode: [channel && channel.chanCode, [Validators.required]],
      accessMode: [channel && channel.accessMode, [Validators.required]],
      ain: [
        channel && channel.ain,
        [Validators.required, Validators.pattern(onlyNumberReg), Validators.maxLength(AMEAINMaxLength)],
        [localUniqueValidator],
      ],
      first3DigitsOfSENumber: [
        channel && channel.first3DigitsOfSENumber,
        [Validators.required, Validators.pattern(F3SENumPattern)],
      ],
      currencies: [channel && channel.currencies, [Validators.required]],
      fee: [
        channel && numScale(channel.fee, 2),
        [Validators.required, Validators.min(0), Validators.max(10), Validators.pattern(TransactionFeeReg)],
      ],
      chanMerName: [
        channel && channel.chanMerName,
        [Validators.required, Validators.maxLength(ChannelMerchantNameMaxLength)],
      ],
      isLoaded: [channel && channel.isLoaded],
    }
  }

  genUPIValidateRules = (channel: ICardChannelUpiExpress): { [key: string]: any } => {
    const localUniqueValidator = this.getLocalUniqueValidatorByChanCode(CardChanCodeValue.UPI)
    return {
      id: [null, []],
      chanCode: [channel && channel.chanCode, [Validators.required]],
      accessMode: [channel && channel.accessMode, [Validators.required]],
      ain: [
        channel && channel.ain,
        [
          Validators.required,
          Validators.minLength(UPIAINLength),
          Validators.maxLength(UPIAINLength),
          Validators.pattern(onlyNumberReg),
        ],
        [localUniqueValidator],
      ],
      fin: [
        channel && channel.fin,
        [
          Validators.required,
          Validators.minLength(UPIAINLength),
          Validators.maxLength(UPIAINLength),
          Validators.pattern(onlyNumberReg),
        ],
      ],
      lineIP: [
        channel && channel.lineIP,
        [Validators.required, Validators.maxLength(IPMaxLength), Validators.pattern(IPPattern)],
      ],
      port: [
        channel && channel.port,
        [Validators.required, Validators.maxLength(PortMaxLength), Validators.pattern(onlyNumberReg)],
      ],
      currencies: [channel && channel.currencies, [Validators.required]],
      fee: [
        channel && numScale(channel.fee, 2),
        [Validators.required, Validators.min(0), Validators.max(10), Validators.pattern(TransactionFeeReg)],
      ],
      chanMerName: [
        channel && channel.chanMerName,
        [Validators.required, Validators.maxLength(ChannelMerchantNameMaxLength)],
      ],
      remark: [channel && channel.remark, [Validators.maxLength(UPIChannelRemarkMaxLength)]],
      isLoaded: [channel && channel.isLoaded],
    }
  }

  private trans(str: string, params?: Object): string {
    return this.i18n.fanyi(str, params)
  }

  private getLocalUniqueValidatorByChanCode(
    chanCode: CardChanCodeValue,
  ): (control: FormControl) => Observable<ValidationErrors> {
    const uniqueKey = getUniqueKey(chanCode)
    return this.getLocalUniqueValidator(chanCode, uniqueKey)
  }

  private getLocalUniqueValidator = (chanCode: string, uniqueKey: string) => (control: FormControl) => {
    return new Observable((observer: Observer<ValidationErrors | null>) => {
      const chanMerID = control.value
      let localUnique = true
      this.localCardChannels.forEach(item => {
        if (item.chanCode === chanCode && item[uniqueKey] === chanMerID) {
          localUnique = false
        }
      })
      if (!localUnique) {
        control.setErrors({ existed: true })
        observer.next(control.errors)
      } else {
        control.setErrors(null)
      }
      observer.complete()
    })
  }
}
